<template>
  <view class="top" :style="navigateStyle">
    <view :style="datetimePickerStyle" style="padding: 0 20rpx; box-sizing: border-box;">
      <uni-datetime-picker v-model="timeRange" type="daterange"></uni-datetime-picker>
    </view>
    <!-- 表头行 -->
    <view class="uni-table-tr">
      <view v-for="item in columns" :key="item.prop" class="uni-table-th" :class="{ 'table--border': border }"
        :style="{ width: customWidth(item.width) + 'px', 'text-align': 'center' }">
        {{ item.label }}
      </view>
    </view>
  </view>
  <mescroll-body @init="mescrollInit" :top="mescrollTop" :i18n="i18nOps" bottom="46px" @down="downCallback"
    @up="upCallback" :up="upOptions">
    <view class="uni-table-scroll table--border" :class="{ 'border-none': !noData }">
      <view class="uni-table table--stripe">
        <!-- 表格数据行 -->
        <view class="uni-table-tr" v-for="row in tableData" :key="row._id">
          <view v-for="item in columns" :key="item.prop" class="uni-table-td" :class="{ 'table--border': border }"
            :style="{ width: customWidth(item.width) + 'px', 'text-align': 'center' }">
            <template v-if="item.prop === 'action'">
              <text @click="rowEdit(row)"> 编辑 </text>
              <text @click="rowDel(row)" style="color: red"> 删除 </text>
            </template>
            <template v-else>
              {{ item.format ? item.format(row) : row[item.prop] }}
            </template>
          </view>
        </view>
        <view v-if="noData" class="uni-table-loading">
          <view class="uni-table-text" :class="{ 'empty-border': border }">暂无更多数据</view>
        </view>
        <view v-if="loading" class="uni-table-mask" :class="{ 'empty-border': border }">
          <div class="uni-table--loader"></div>
        </view>
      </view>
    </view>
  </mescroll-body>
  <view class="bottom">
    <view class="button button-info" @click="bindDateChange">导出</view>
    <view class="button button-primary" @click="handleAdd">新增</view>
  </view>
</template>

<script setup>
import { ref, watch } from 'vue';
import { onPageScroll, onReachBottom, onShow, onLoad } from '@dcloudio/uni-app';
const XLSX = require('../../static/xlsx.core.min.js');
import { getAccountList, getAccountPage, delAccount } from '@/api/index';
import useMescroll from '@/uni_modules/mescroll-uni/hooks/useMescroll.js';
import Big from 'big.js';

const { mescrollInit, downCallback } = useMescroll(onPageScroll, onReachBottom);

const timeRange = ref([]);
const canReset = ref(false);
const tableData = ref([]);
const deviceOrientation = ref('portrait'); // portrait 竖屏， landscape 横屏
const mescrollRef = ref(null);
const navigateStyle = ref('width: 0; height: 0;')
const datetimePickerStyle = ref('width: 0; height: 0;')
const mescrollTop = ref('0px');
const upOptions = {
  page: {
    num: 0,
    size: 20,
  },
  empty: {
    icon: '/static/empty.svg',
  },
  toTop: {
    src: '/static/totop.svg',
    offset:100
  }
};
const i18nOps = {
  zh: {
    up: {
      textNoMore: '-- 没有更多数据了 --',
    }
  }
}

function handleAdd() {
  uni.navigateTo({ url: '/pages/index/add' });
}

function rowEdit(row) {
  uni.navigateTo({ url: '/pages/index/add?id=' + row._id });
}

function rowDel(row) {
  uni.showModal({
    title: '提示',
    content: '确定删除吗？',
    success: async (res) => {
      if (res.cancel) {
        return;
      }
      await delAccount({ _id: row._id });
      uni.showToast({ title: '删除成功' });
      mescrollRef.value.resetUpScroll();
      mescrollRef.value.scrollTo(0, 0);
    },
  });
}

const upCallback = async (mescroll) => {
  mescrollRef.value = mescroll;
  const [startTime, endTime] = timeRange.value
  const params = { page: mescroll.num, size: mescroll.size }
  if (startTime && endTime) {
    params.startTime = startTime
    params.endTime = endTime
  }
  getAccountPage(params)
    .then((res) => {
      const curPageData = res.data || []; // 当前页数据
      if (mescroll.num == 1) tableData.value = []; // 第一页需手动制空列表
      tableData.value = tableData.value.concat(curPageData); //追加新数据
      mescroll.endSuccess(curPageData.length); // 请求成功, 结束加载
    })
    .catch(() => {
      mescroll.endErr(); // 请求失败, 结束加载
    });
};

function customWidth(width) {
  if (typeof width === 'number') {
    return width
  } else if (typeof width === 'string') {
    let regexHaveUnitPx = new RegExp(/^[1-9][0-9]*px$/g)
    let regexHaveUnitRpx = new RegExp(/^[1-9][0-9]*rpx$/g)
    let regexHaveNotUnit = new RegExp(/^[1-9][0-9]*$/g)
    if (width.match(regexHaveUnitPx) !== null) { // 携带了 px
      return width.replace('px', '')
    } else if (width.match(regexHaveUnitRpx) !== null) { // 携带了 rpx
      let numberRpx = Number(width.replace('rpx', ''))
      let widthCoe = uni.getSystemInfoSync().screenWidth / 750
      return Math.round(numberRpx * widthCoe)
    } else if (width.match(regexHaveNotUnit) !== null) { // 未携带 rpx或px 的纯数字 String
      return width
    } else { // 不符合格式
      return ''
    }
  } else {
    return ''
  }
}

function refresh() {
  canReset.value && mescrollRef.value.resetUpScroll(); // 重置列表数据为第一页
  canReset.value && mescrollRef.value.scrollTo(0, 0); // 重置列表数据为第一页时,建议把滚动条也重置到顶部,避免无法再次翻页的问题
  canReset.value = true; // 过滤第一次的onShow事件,避免初始化界面时重复触发upCallback, 无需配置auto:false
}

function bindDateChange() {
  exportExcel()
}

async function exportExcel() {
  const [startTime, endTime] = timeRange.value
  const params = { startTime, endTime }
  const res = await getAccountList(params);
  const data = res.data || [];
  const fileData = createExcel(data);
  let filePath = `${wx.env.USER_DATA_PATH}/用户表.xlsx`;
  writeFile(fileData, filePath);
}

function createExcel(data) {
  const sheet = [];
  const title = ['日期', '型号', '单价', '数量', '总价'];
  sheet.push(title);
  let _totalPrice = new Big(0);
  let totalNumber = new Big(0);
  data.forEach((item) => {
    const totalPrice = new Big(item.price).times(item.number);
    totalNumber = totalNumber.plus(item.number)
    _totalPrice = _totalPrice.plus(totalPrice)
    sheet.push([item.creatTime, item.modelName, item.price, item.number, totalPrice.toNumber()]);
  });
  sheet.push(['总和', '', '', totalNumber.toNumber(), _totalPrice.toNumber()]);
  // XLSX插件使用
  var ws = XLSX.utils.aoa_to_sheet(sheet);
  var wb = XLSX.utils.book_new();
  addExcilStyle(ws)
  XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');
  return XLSX.write(wb, {
    bookType: 'xlsx',
    type: 'base64',
  });
}

// 写文件
function writeFile(fileData, filePath) {
  const fs = wx.getFileSystemManager();
  fs.writeFile({
    filePath: filePath,
    data: fileData,
    encoding: 'base64',
    bookSST: true,
    success() {
      const sysInfo = wx.getSystemInfoSync();
      // 导出
      if (sysInfo.platform.toLowerCase().indexOf('windows') >= 0) {
        // 电脑PC端导出
        wx.saveFileToDisk({
          filePath: filePath,
          success(res) {
            console.log(res);
          },
          fail(res) {
            console.error(res);
            util.tips('导出失败');
          },
        });
      } else {
        // 手机端导出
        // 打开文档
        wx.openDocument({
          filePath: filePath,
          showMenu: true,
          success: function (res) {
            console.log('打开文档成功');
          },
          fail: console.error,
        });
      }
    },
    fail(res) {
      console.error(res);
      if (res.errMsg.indexOf('locked')) {
        wx.showModal({
          title: '提示',
          content: '文档已打开，请先关闭',
        });
      }
    },
  });
}

function addExcilStyle(sheet) {
  for (const key in sheet) {
    if (Number(key.slice(1)) == 1) { //设置第一行【表头】样式
      sheet[key].s = {
        font: {
          sz: 14,
          // bold: true,
          // color: {
          //   rgb: "0000FF"
          // }
        },
        fill: {
          bgColor: {
            indexed: 64
          },
          fgColor: {
            rgb: "CCCCCC" //填16进制
          }
        }
      }; //<====设置xlsx单元格样式
    }
  }
}

function onResize() {
  const { left, height, top, bottom } = wx.getMenuButtonBoundingClientRect()
  navigateStyle.value = `padding-top: ${top}px`
  datetimePickerStyle.value = `width: ${left}px;height: height: ${height}px`
  mescrollTop.value = bottom + 34 + "px"
}

onShow(() => {
  refresh()
});

onLoad(() => {
  uni.onWindowResize((e) => {
    deviceOrientation.value = e.deviceOrientation
    onResize()
  })
  onResize()
})

watch(timeRange, refresh)

const columns = [
  {
    label: '日期',
    prop: 'creatTime',
    width: '150rpx',
  },
  {
    label: '型号',
    prop: 'modelName',
    width: '120rpx',
  },
  {
    label: '单价',
    prop: 'price',
    width: '120rpx',
  },
  {
    label: '数量',
    prop: 'number',
    width: '120rpx',
  },
  {
    label: '总价',
    prop: 'totalPrice',
    width: '120rpx',
    format: (row) => new Big(row.price).times(row.number).toNumber(),
  },
  {
    label: '操作',
    prop: 'action',
    width: '120rpx',
  },
];
</script>

<style lang="scss">
.container {
  padding-top: var(--status-bar-height);
  background-color: #fff;
  display: flex;
  flex-direction: column;
}

.top {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 2;
  background-color: #fff;
  width: 100%;
}

:deep(.uni-date__x-input),
:deep(.range-separator) {
  height: 30px !important;
  line-height: 30px !important;
}

.uni-table-td {
  padding: 10rpx 0 !important;
  font-size: 24rpx !important;
}

.bottom {
  position: fixed;
  bottom: 0;
  left: 0;
  width: 100%;
  display: flex;
  border-radius: 10rpx 10rpx 0 0;
  overflow: hidden;
}

$border-color: #ebeef5;

.uni-table-scroll {
  width: 100%;
  overflow-x: auto;

  .uni-table {
    position: relative;
    width: 100%;
    border-radius: 5px;
    background-color: #fff;
    box-sizing: border-box;
    display: table;
    overflow-x: auto;
  }

  .table--stripe {

    /* #ifndef APP-NVUE */
    ::v-deep .uni-table-tr:nth-child(2n + 3) {
      background-color: #fafafa;
    }

    /* #endif */
  }

  /* 表格加载、无数据样式 */
  .uni-table-loading {
    position: relative;
    /* #ifndef APP-NVUE */
    display: table-row;
    /* #endif */
    height: 50px;
    line-height: 50px;
    overflow: hidden;
    box-sizing: border-box;

    .uni-table-text {
      position: absolute;
      right: 0;
      left: 0;
      text-align: center;
      font-size: 14px;
      color: #999;
    }
  }

  .empty-border {
    border-right: 1px $border-color solid;
  }

  .uni-table-mask {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    background-color: rgba(255, 255, 255, 0.8);
    z-index: 99;
    /* #ifndef APP-NVUE */
    display: flex;
    margin: auto;
    transition: all 0.5s;
    /* #endif */
    justify-content: center;
    align-items: center;

    .uni-table--loader {
      width: 30px;
      height: 30px;
      border: 2px solid #aaa;
      border-radius: 50%;
      /* #ifndef APP-NVUE */
      animation: 2s uni-table--loader linear infinite;
      /* #endif */
      position: relative;
    }
  }
}

.uni-table-tr:nth-child(n + 2) {
  &:hover {
    background-color: #f5f7fa;
  }
}

.uni-table-tr {
  /* #ifndef APP-NVUE */
  display: table-row;
  transition: all 0.3s;
  box-sizing: border-box;
  width: 100%;

  /* #endif */
  .uni-table-th {
    height: 33px;
    line-height: 33px;
    /* #ifndef APP-NVUE */
    display: table-cell;
    box-sizing: border-box;
    /* #endif */
    font-size: 14px;
    font-weight: bold;
    color: #909399;
    border-bottom: 1px $border-color solid;
  }

  .uni-table-td {
    display: table-cell;
    padding: 8px 10px;
    font-size: 14px;
    border-bottom: 1px $border-color solid;
    font-weight: 400;
    color: #606266;
    line-height: 23px;
    box-sizing: border-box;
  }
}

.border-none {
  /* #ifndef APP-NVUE */
  border-bottom: none;
  /* #endif */
}

.button {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 1;
  height: 38px;
  color: #fff;
}

.button-primary {
  background-color: #04b27c;
}

.button-info {
  background-color: #909399;
}
</style>
